#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include "thread2.h"
#include "thread1.h"
#include "msg_queue.h"
#include "log_utils.h"
#include "thread4.h"
#include "thread5.h"

#define CONFIG_FILE "device_config.txt"
#define TCP_PORT 20163
#define BUFFER_SIZE 1024
#define CHECK_INTERVAL 5  // 检查TCP连接状态的间隔（秒）
#define RECONNECT_INTERVAL 10  // TCP重连间隔（秒）
#define MAX_RETRY_COUNT 5  // 最大重连尝试次数
#define HELLO_INTERVAL 1  // 发送hello world的间隔（秒）

// 全局变量，表示TCP连接状态
int g_tcp_connection_status = TCP_CONNECTION_FAILURE;

// TCP连接套接字
static int g_tcp_socket = -1;

// 从配置文件中获取服务器IP地址
static int get_server_ip(char *server_ip, int ip_max_len) {
    FILE *fp;
    char line[512];
    char *ptr, *value;
    int ip_found = 0;
    
    fp = fopen(CONFIG_FILE, "r");
    if (fp == NULL) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "无法打开配置文件 %s", CONFIG_FILE);
        return -1;
    }
    
    // 默认值
    strncpy(server_ip, "192.168.1.1", ip_max_len - 1);
    server_ip[ip_max_len - 1] = '\0';
    
    while (fgets(line, sizeof(line), fp)) {
        // 查找服务器IP地址
        ptr = strstr(line, "\"assigned_ip\"");
        if (ptr) {
            ptr = strchr(ptr + 12, ':');
            if (ptr) {
                ptr++;
                while (*ptr == ' ' || *ptr == '\t') ptr++;
                
                if (*ptr == '"') {
                    value = ++ptr;
                    ptr = strchr(value, '"');
                    if (ptr) {
                        *ptr = '\0';
                        strncpy(server_ip, value, ip_max_len - 1);
                        server_ip[ip_max_len - 1] = '\0';
                        ip_found = 1;
                        break;
                    }
                }
            }
        }
    }
    
    fclose(fp);
    
    if (ip_found) {
        LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "从配置文件读取到服务器IP: %s", server_ip);
        return 0;
    } else {
        LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "未在配置文件中找到服务器IP，使用默认值: %s", server_ip);
        return 0;  // 仍然返回成功，因为使用了默认值
    }
}

// 设置套接字为非阻塞模式
static int set_nonblocking(int sock) {
    int flags = fcntl(sock, F_GETFL, 0);
    if (flags == -1) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "fcntl F_GETFL: %s", strerror(errno));
        return -1;
    }
    
    if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "fcntl F_SETFL O_NONBLOCK: %s", strerror(errno));
        return -1;
    }
    
    return 0;
}

/**
 * 功能块1: 建立TCP连接
 * 
 * 与TCP服务器建立连接
 * 
 * 返回值: 连接的套接字，失败返回-1
 */
static int establish_tcp_connection(const char *server_ip, int server_port) {
    int sock;
    struct sockaddr_in server_addr;
    
    // 创建套接字
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "创建TCP套接字失败: %s", strerror(errno));
        return -1;
    }
    
    // 设置为非阻塞模式
    if (set_nonblocking(sock) < 0) {
        close(sock);
        return -1;
    }
    
    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(server_port);
    
    if (inet_pton(AF_INET, server_ip, &server_addr.sin_addr) <= 0) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "无效的服务器IP地址: %s", server_ip);
        close(sock);
        return -1;
    }
    
    // 连接服务器（非阻塞模式）
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "正在连接TCP服务器 %s:%d...", server_ip, server_port);
    int ret = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
    
    if (ret < 0) {
        if (errno == EINPROGRESS) {
            // 连接正在进行中，需要使用select等待
            fd_set write_fds;
            struct timeval timeout;
            
            FD_ZERO(&write_fds);
            FD_SET(sock, &write_fds);
            
            // 设置连接超时时间为3秒
            timeout.tv_sec = 3;
            timeout.tv_usec = 0;
            
            ret = select(sock + 1, NULL, &write_fds, NULL, &timeout);
            
            if (ret < 0) {
                LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "select错误: %s", strerror(errno));
                close(sock);
                return -1;
            } else if (ret == 0) {
                // 连接超时
                LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "连接TCP服务器超时");
                close(sock);
                return -1;
            } else {
                // 检查套接字是否真的已连接
                int error = 0;
                socklen_t len = sizeof(error);
                
                if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error != 0) {
                    LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "连接失败: %s", strerror(error));
                    close(sock);
                    return -1;
                }
            }
        } else {
            // 其他连接错误
            LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "连接TCP服务器失败: %s", strerror(errno));
            close(sock);
            return -1;
        }
    }
    
    // 连接成功，恢复为阻塞模式
    int flags = fcntl(sock, F_GETFL, 0);
    fcntl(sock, F_SETFL, flags & (~O_NONBLOCK));
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "成功连接到TCP服务器 %s:%d", server_ip, server_port);
    
    return sock;
}

/**
 * 功能块2: 检查TCP连接状态
 * 
 * 检查与服务器的TCP连接是否正常
 * 
 * 返回值: 1表示连接正常，0表示连接异常
 */
static int check_tcp_connection(int sock) {
    if (sock < 0) {
        return 0;  // 无效的套接字
    }
    
    // 使用非阻塞模式发送0字节数据来检查连接是否仍然有效
    char buf[1] = {0};
    int flags = fcntl(sock, F_GETFL, 0);
    fcntl(sock, F_SETFL, flags | O_NONBLOCK);
    
    int ret = send(sock, buf, 0, MSG_NOSIGNAL);
    
    // 恢复原始标志
    fcntl(sock, F_SETFL, flags);
    
    if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
        // 连接已断开
        LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "TCP连接检查失败: %s", strerror(errno));
        return 0;
    }
    
    return 1;  // 连接正常
}

/**
 * 功能块3: 处理客户端与服务器的通信
 * 
 * 实现客户端与服务器之间的通信逻辑
 * 
 * 返回值: 0表示通信结束，-1表示通信错误
 */
static int handle_tcp_communication(int sock) {
    char recv_buffer[BUFFER_SIZE];
    int recv_len;
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "开始TCP通信处理...");
    
    // 等待服务器的欢迎消息
    memset(recv_buffer, 0, sizeof(recv_buffer));
    recv_len = recv(sock, recv_buffer, sizeof(recv_buffer) - 1, 0);
    
    if (recv_len > 0) {
        recv_buffer[recv_len] = '\0';
        LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "收到服务器欢迎消息: %s", recv_buffer);
        
        // 服务器连接建立成功
        return 0;
    } else if (recv_len == 0) {
        LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "服务器已关闭连接");
        return -1;
    } else {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "接收服务器欢迎消息失败: %s", strerror(errno));
        return -1;
    }
}

/**
 * 功能块4: 客户端主循环
 * 
 * 在TCP连接建立后的主通信循环
 * 
 * 返回值: 0表示正常退出，-1表示发生错误
 */
static int tcp_client_main_loop(int sock) {
    char send_buffer[BUFFER_SIZE];
    char recv_buffer[BUFFER_SIZE];
    int recv_len;
    fd_set read_fds;
    struct timeval timeout;
    time_t last_status_time = time(NULL);
    time_t current_time;
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "进入TCP客户端主循环...");
    
    while (1) {
        // 检查WiFi连接状态
        if (g_wifi_connection_status != WIFI_CONNECTION_SUCCESS) {
            LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "WiFi连接已断开，退出TCP客户端循环");
            return -1;
        }
        
        // 设置select超时为0.1秒，提高消息发送的及时性
        FD_ZERO(&read_fds);
        FD_SET(sock, &read_fds);
        timeout.tv_sec = 0;
        timeout.tv_usec = 100000;  // 100ms
        
        int ret = select(sock + 1, &read_fds, NULL, NULL, &timeout);
        
        if (ret < 0) {
            LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "select错误: %s", strerror(errno));
            return -1;
        } else if (ret > 0) {
            // 有数据可读
            if (FD_ISSET(sock, &read_fds)) {
                memset(recv_buffer, 0, sizeof(recv_buffer));
                recv_len = recv(sock, recv_buffer, sizeof(recv_buffer) - 1, 0);
                
                if (recv_len > 0) {
                    // 成功接收数据
                    recv_buffer[recv_len] = '\0';
                    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "收到服务器消息: %s", recv_buffer);
                } else if (recv_len == 0) {
                    // 服务器关闭连接
                    LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "服务器关闭了连接");
                    return -1;
                } else {
                    // 接收错误
                    LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "接收数据失败: %s", strerror(errno));
                    return -1;
                }
            }
        }
        
        // 获取当前时间
        current_time = time(NULL);
        
        // 每秒发送接近传感器状态消息
        if (current_time - last_status_time >= HELLO_INTERVAL) {
            // 获取接近传感器1状态
            proximity_sensor_t sensor1_state;
            int sensor1_ret = get_proximity_sensor_state(&sensor1_state);
            
            // 获取接近传感器2状态
            proximity_sensor2_t sensor2_state;
            int sensor2_ret = get_proximity_sensor2_state(&sensor2_state);
            
            // 构建状态消息
            if (sensor1_ret == 0 && sensor2_ret == 0) {
                snprintf(send_buffer, sizeof(send_buffer), 
                        "PROX_STATUS: sensor1=%s,sensor2=%s,timestamp=%u", 
                        sensor1_state.sensor1_state == 0 ? "valid" : "invalid",
                        sensor2_state.sensor2_state == 0 ? "valid" : "invalid",
                        (unsigned int)time(NULL));
                
                // INFO级别日志：记录接近传感器状态
                LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, 
                        "接近传感器状态 - 传感器1: %s, 传感器2: %s, 时间戳: %u", 
                        sensor1_state.sensor1_state == 0 ? "valid(检测到物体)" : "invalid(未检测到物体)",
                        sensor2_state.sensor2_state == 0 ? "valid(检测到物体)" : "invalid(未检测到物体)",
                        (unsigned int)time(NULL));
                
                // INFO级别日志：记录TCP发送状态
                LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, 
                        "TCP发送接近传感器状态成功: %s", send_buffer);
                        
            } else {
                // 如果获取状态失败，发送错误信息
                snprintf(send_buffer, sizeof(send_buffer), 
                        "PROX_STATUS: sensor1=error,sensor2=error,timestamp=%u", 
                        (unsigned int)time(NULL));
                
                // INFO级别日志：记录获取状态失败
                LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, 
                        "获取接近传感器状态失败 - 传感器1: %s, 传感器2: %s", 
                        sensor1_ret == 0 ? "成功" : "失败",
                        sensor2_ret == 0 ? "成功" : "失败");
                
                LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "获取接近传感器状态失败");
            }
            
            if (send(sock, send_buffer, strlen(send_buffer), 0) < 0) {
                LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "发送接近传感器状态消息失败: %s", strerror(errno));
                return -1;
            }
            
            LOG_DEBUG(LOG_TO_FILE, LOG_MODULE_TCP, "已发送接近传感器状态: %s", send_buffer);
            last_status_time = current_time;
        }
        
        // 短暂休眠，避免CPU占用过高
        usleep(10000);  // 10ms
    }
    
    return 0;
}

/**
 * 线程2主函数 - TCP客户端管理
 */
void *thread2_function(void *arg) {
    (void)arg;  // 标记参数为未使用
    int wifi_status_changed = 0;
    int wifi_status_last = WIFI_CONNECTION_FAILURE;
    int tcp_retry_count = 0;
    char server_ip[20] = {0};
    struct msg_data msg;
    time_t last_connect_time = 0;
    time_t current_time;
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "线程2: TCP客户端管理启动");
    
    // 主循环
    while (1) {
        // 检查WiFi连接状态是否变化
        if (wifi_status_last != g_wifi_connection_status) {
            wifi_status_changed = 1;
            wifi_status_last = g_wifi_connection_status;
            
            if (g_wifi_connection_status == WIFI_CONNECTION_SUCCESS) {
                LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "检测到WiFi连接状态变为成功");
            } else {
                LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "检测到WiFi连接状态变为失败");
                
                // WiFi断开，关闭当前TCP连接
                if (g_tcp_socket >= 0) {
                    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "由于WiFi断开，关闭TCP连接");
                    close(g_tcp_socket);
                    g_tcp_socket = -1;
                    g_tcp_connection_status = TCP_CONNECTION_FAILURE;
                }
            }
        }
        
        // 检查消息队列是否有WiFi重置消息
        if (g_msg_queue_id >= 0) {
            if (recv_msg(g_msg_queue_id, MSG_TYPE_WIFI_RESET, &msg, 0) > 0) {
                LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "接收到WiFi重置消息: %s", msg.msg_text);
                wifi_status_changed = 1;
                
                // 关闭现有TCP连接，准备重连
                if (g_tcp_socket >= 0) {
                    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "由于WiFi重置，关闭现有TCP连接");
                    close(g_tcp_socket);
                    g_tcp_socket = -1;
                    g_tcp_connection_status = TCP_CONNECTION_FAILURE;
                }
                
                // 重置重试计数
                tcp_retry_count = 0;
            }
        }
        
        // 当WiFi连接正常时，处理TCP连接
        if (g_wifi_connection_status == WIFI_CONNECTION_SUCCESS) {
            current_time = time(NULL);
            
            // 如果TCP连接未建立或已断开，尝试建立连接
            if (g_tcp_socket < 0) {
                // 限制重连频率
                if (wifi_status_changed || current_time - last_connect_time >= RECONNECT_INTERVAL) {
                    // 读取服务器IP地址
                    if (get_server_ip(server_ip, sizeof(server_ip)) != 0) {
                        LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "获取服务器IP地址失败，使用默认值");
                        strncpy(server_ip, "192.168.1.1", sizeof(server_ip) - 1);
                    }
                    
                    // 尝试建立TCP连接
                    LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "尝试建立TCP连接 (尝试 %d/%d)", tcp_retry_count + 1, MAX_RETRY_COUNT);
                    g_tcp_socket = establish_tcp_connection(server_ip, TCP_PORT);
                    
                    if (g_tcp_socket >= 0) {
                        // 连接成功
                        g_tcp_connection_status = TCP_CONNECTION_SUCCESS;
                        LOG_INFO(LOG_TO_FILE, LOG_MODULE_TCP, "TCP连接成功建立，套接字: %d", g_tcp_socket);
                        
                        // 初始化通信
                        if (handle_tcp_communication(g_tcp_socket) == 0) {
                            // 进入通信主循环
                            if (tcp_client_main_loop(g_tcp_socket) != 0) {
                                LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "TCP通信出错，断开连接");
                                close(g_tcp_socket);
                                g_tcp_socket = -1;
                                g_tcp_connection_status = TCP_CONNECTION_FAILURE;
                            }
                        } else {
                            // 初始化通信失败
                            LOG_ERROR(LOG_TO_FILE, LOG_MODULE_TCP, "TCP初始化通信失败，关闭连接");
                            close(g_tcp_socket);
                            g_tcp_socket = -1;
                            g_tcp_connection_status = TCP_CONNECTION_FAILURE;
                        }
                    } else {
                        // 连接失败，增加重试计数
                        tcp_retry_count++;
                        if (tcp_retry_count >= MAX_RETRY_COUNT) {
                            LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "达到最大TCP重试次数 (%d)，暂停重连", MAX_RETRY_COUNT);
                            tcp_retry_count = 0;  // 重置计数，后续会再次尝试
                            sleep(RECONNECT_INTERVAL * 2);  // 等待更长时间
                        }
                    }
                    
                    last_connect_time = current_time;
                    wifi_status_changed = 0;
                }
            } else {
                // 检查现有TCP连接是否正常
                if (!check_tcp_connection(g_tcp_socket)) {
                    LOG_WARN(LOG_TO_FILE, LOG_MODULE_TCP, "TCP连接检查失败，关闭连接");
                    close(g_tcp_socket);
                    g_tcp_socket = -1;
                    g_tcp_connection_status = TCP_CONNECTION_FAILURE;
                    tcp_retry_count = 0;  // 重置重试计数，下次循环将重新连接
                }
            }
        }
        
        // 休眠一段时间
        sleep(CHECK_INTERVAL);
    }
    
    return NULL;
} 